import type {
  ColumnCompositionProps,
  CrudBinding,
  CrudOptions,
  FormItemProps,
  FormScopeContext,
  FsSetupOptions,
  ScopeContext,
  ValueBuilderContext,
} from '@fast-crud/fast-crud';
import type { FsUploaderFormRequestOptions } from '@fast-crud/fast-extends';
import type { FsEditorWang5Config } from '@fast-crud/fast-extends/dist/d/editor/type/config';

import type { App } from 'vue';

import { computed } from 'vue';

import { i18n } from '@vben/locales';
import { isNullOrUnDef } from '@vben/utils';

import { QuestionCircleOutlined } from '@ant-design/icons-vue';
import {
  FastCrud,
  registerMergeColumnPlugin,
  useMerge,
  useTypes,
} from '@fast-crud/fast-crud';
import {
  FsExtendsCopyable,
  FsExtendsEditor,
  FsExtendsJson,
  FsExtendsTime,
  FsExtendsUploader,
} from '@fast-crud/fast-extends';
import ui from '@fast-crud/ui-antdv4';
import Antdv, { notification } from 'ant-design-vue';
import dayjs from 'dayjs';
import { isFunction } from 'lodash-es';

import { uploadFile } from '#/api';
import { $t } from '#/locales';
import { useDictStore } from '#/store';

import { columnSizeSaver } from './column-size-saver';
import { transformQuery, transformRes } from './common';
import { useCrudPermission } from './setup-fast-crud-permission';

import '@fast-crud/fast-crud/dist/style.css';
import '@fast-crud/ui-antdv4/dist/style.css';
import '@fast-crud/fast-extends/dist/style.css';
import './setup-fast-crud.less';

const { merge } = useMerge();
export function registerFastCrud(app: App) {
  app.use(Antdv);
  app.use(ui);
  app.use(FastCrud, {
    i18n,
    logger: { off: { tableColumns: false } },
    async dictRequest({ dict }) {
      const custom: any = dict.custom;
      const dictStore = useDictStore();
      return dictStore.getDictItemOptionList(custom.type);
    },
    commonOptions(props: any) {
      const { crudExpose } = props;
      const crudBinding = crudExpose?.crudBinding;
      const opts: CrudBinding = {
        settings: {
          // 默认开启 查看页面使用自定义组件
          viewFormUseCellComponent: true,
        },
        toolbar: {
          compact: false,
          buttons: {
            compact: { show: false },
          },
          columnsFilter: {
            async onReset() {
              columnSizeSaver.clear();
            },
          },
        },
        search: {
          buttons: {
            search: {
              style: 'marginLeft:-2px',
            },
          },
        },
        container: {
          is: 'fs-layout-card',
        },
        rowHandle: {
          width: 180,
          align: 'left',
          // 固定右侧 不建议设置成全局
          fixed: 'right',
          buttons: {
            view: { order: 1, size: 'small', type: 'link', icon: undefined },
            edit: { order: 2, size: 'small', type: 'link', icon: undefined },
            remove: {
              order: 3,
              size: 'small',
              type: 'link',
              icon: '',
              // 重写 render 默认的 confirm 没有 pop-confirm 操作友好
              render(scope: any) {
                function confirm() {
                  const { row, index } = scope;
                  crudExpose.doRemove({ row, index }, { noConfirm: true });
                }
                return (
                  <a-popconfirm
                    cancel-text={$t('common.cancelText')}
                    ok-text={$t('common.delete')}
                    onConfirm={confirm}
                    placement="bottom"
                    title={$t('common.tips.confirmDelete')}
                    v-slots={{
                      icon: () => (
                        <QuestionCircleOutlined style={{ color: 'red' }} />
                      ),
                    }}
                  >
                    <fs-button class="ant-btn-sm" danger type="link">
                      {$t('common.delete')}
                    </fs-button>
                  </a-popconfirm>
                );
              },
            },
            copy: {
              show: true,
              text: $t('common.title.copy'),
              dropdown: true,
            },
          },
          dropdown: { more: { type: 'link' } },
        },
        table: {
          size: 'small',
          scroll: {
            // 需要设置它，否则滚动条拖动时，表头不会动
            fixed: false,
          },
          pagination: false,
          onResizeColumn: (w: number, col: any) => {
            if (
              crudBinding.value?.table?.columnsMap &&
              crudBinding.value?.table?.columnsMap[col.key]
            ) {
              crudBinding.value.table.columnsMap[col.key].width = w;
              columnSizeSaver.save(
                `${crudExpose.crudBinding.value.id}_${col.key}`,
                w,
              );
            }
          },
        },
        request: {
          transformQuery,
          transformRes,
        },
        form: {
          // 表单布局
          display: 'flex',
          labelWidth: '120px', // 表单label宽度
          wrapper: {
            is: 'a-drawer',
            maskClosable: false,
            saveRemind: true,
          },
          async afterSubmit({ mode }: FormScopeContext) {
            if (mode === 'add') {
              notification.success({ message: $t('common.tips.addSuccess') });
            } else if (mode === 'edit') {
              notification.success({
                message: $t('common.tips.updateSuccess'),
              });
            }
          },
          wrapperCol: { span: null },
          labelCol: {
            // 固定label宽度
            span: null,
            style: { width: '110px' },
          },
          layout: computed(() => {
            // return getLocale.value === LOCALE.ZH_CN ? "horizontal" : "vertical";
            return 'horizontal';
          }),
        },
      };
      const permission = props.context?.permission || null;
      const crudPermission = useCrudPermission({ permission });
      return crudPermission.merge(opts);
    },
  } as FsSetupOptions);

  // 安装editor
  app.use(FsExtendsEditor, {
    // 编辑器的公共配置
    wangEditor5: {
      editorConfig: {
        MENU_CONF: {},
      },
      toolbarConfig: {},
    } as FsEditorWang5Config,
  });
  app.use(FsExtendsJson);
  app.use(FsExtendsTime);
  app.use(FsExtendsCopyable);
  // app.use(FsExtendsInput);
  // 配置uploader 公共参数
  app.use(FsExtendsUploader, {
    defaultType: 'form',
    form: {
      keepName: true,
      name: 'file',
      withCredentials: false,
      uploadRequest: async (options: FsUploaderFormRequestOptions) => {
        const { file, onProgress, param } = options;

        let paramObj = param;
        if (isFunction(param)) {
          paramObj = await param();
        }
        const result = await uploadFile(
          { file, ...paramObj },
          {
            headers: {
              'Content-Type': 'multipart/form-data',
            },
            timeout: 60_000,
            onUploadProgress: (p: any) => {
              onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
            },
          },
        );
        return result.id;
      },
      successHandle(ret: any) {
        // // 上传完成后的结果处理， 此处后台返回的结果应该为 ret = {code:0,msg:'',data:fileUrl}
        // if (!ret.id) {
        //   throw new Error('上传失败');
        // }
        // const fileId = `${ret.basePath}/${ret.filename}`;
        // return {
        //   url: ret.url,
        //   fileId,
        //   key: fileId,
        // };

        return {
          url: ret,
          key: ret,
        };
      },
    },
  } as any);

  function initColumnSetting() {
    // 修改官方字段类型
    // 不要写在页面里，这个是全局的，要写在vue.use(FastCrud)之后
    const { getType, addTypes } = useTypes();
    const selectType = getType('dict-select');
    selectType.column.component.color = 'auto'; // 修改官方的字段类型，设置为支持自动染色

    addTypes({
      'wp-readonly-time': {
        column: { width: 170, align: 'center' },
        addForm: { show: false },
        editForm: { show: false },
        valueBuilder({ value, row, key }: ValueBuilderContext): void {
          if (value !== null) {
            row[key] = dayjs(value);
          }
        },
      },
    });
  }

  initColumnSetting();

  // 默认宽度，支持自动拖动调整列宽
  registerMergeColumnPlugin({
    name: 'resize-column-plugin',
    order: 2,
    handle: (columnProps: ColumnCompositionProps, crudOptions: CrudOptions) => {
      if (!columnProps.column) {
        columnProps.column = {};
      }

      if (
        isNullOrUnDef(columnProps.column.resizable) &&
        !['_index', 'createdTime'].includes(columnProps.key as string)
      ) {
        columnProps.column.resizable = true;
        const savedColumnWidth = columnSizeSaver.get(
          `${crudOptions.id}_${String(columnProps.key)}`,
        );
        if (savedColumnWidth) {
          columnProps.column.width = savedColumnWidth;
        } else if (!columnProps.column.width) {
          columnProps.column.width = 150;
        }
      }
      return columnProps;
    },
  });

  // view 表单 列组件渲染
  const viewFormUseCellComponentPlugin = {
    name: 'viewFormUseCellComponent',
    order: 11,
    handle: (
      columnProps: ColumnCompositionProps = {},
      crudOptions: CrudOptions = {},
    ) => {
      // 全局忽略
      if (!crudOptions.settings?.viewFormUseCellComponent) {
        return columnProps;
      }
      // 当前字段忽略
      if (columnProps.viewForm?.ignoreUseCellComponent) {
        return columnProps;
      }

      // 没有配置type
      if (!columnProps.type) {
        return columnProps;
      }
      // 让viewForm的组件使用cell组件

      const columnComponent = columnProps.column?.component || {};
      const viewFormColumn: FormItemProps = {
        component: columnComponent,
      };
      if (!(columnProps.type as string).includes('dict')) {
        // if (
        //   ['datetime', 'text', 'textarea'].includes(columnProps.type as string) ||
        //   (Array.isArray(columnProps.type) && columnProps.type.includes('text'))
        // ) {
        viewFormColumn.render = (context: ScopeContext) => {
          const { value } = context;
          return <span class="break-words">{value}</span>;
        };
      }
      merge(columnProps, { viewForm: viewFormColumn });
      return columnProps;
    },
  };

  registerMergeColumnPlugin(viewFormUseCellComponentPlugin);
}
